package com.qiyu.security.handler;

import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.qiyu.security.bean.JwtToken;
import com.qiyu.security.util.JwtUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;

/**
 * 其他自动配置类会使用该对象，所以需要注入到IoC容器中
 */
@Component
public class JwtRealm extends AuthorizingRealm {
    
    @Autowired
    private HttpServletRequest httpServletRequest;
    
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }
    
    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return new SimpleAuthorizationInfo(new HashSet<>());
    }
    
    /**
     * 获取认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getCredentials();
        if (token == null) {
            throw new AuthenticationException("请先登录");
        }
        String userId = JwtUtil.getUserId(token);
        if (userId == null) {
            throw new AuthenticationException("用户不存在");
        }
        
        //校验token
        try {
            String uri = httpServletRequest.getRequestURI().substring(1);
            int i = uri.indexOf("/");
            String scene = uri;
            if (i > 0) {
                scene = uri.substring(0, i);
            }
            JwtUtil.verify(token, scene);
        } catch (TokenExpiredException e) {
            throw new UnknownAccountException("TOKEN已过期");
        } catch (SignatureVerificationException e) {
            throw new IncorrectCredentialsException("TOKEN校验出错");
        } catch (Exception e) {
            throw new IncorrectCredentialsException("密码错误");
        }
        
        return new SimpleAuthenticationInfo(token, token, "JwtRealm");
    }
}
